home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / site-packages / impacket / nmb.py < prev    next >
Text File  |  2006-05-23  |  29KB  |  777 lines

  1. # Copyright (c) 2003-2006 CORE Security Technologies
  2. #
  3. # This software is provided under under a slightly modified version
  4. # of the Apache Software License. See the accompanying LICENSE file
  5. # for more information.
  6. #
  7. # $Id: nmb.py,v 1.4 2006/05/23 21:19:25 gera Exp $
  8. #
  9.  
  10.  
  11. # -*- mode: python; tab-width: 4 -*-
  12. #
  13. # Copyright (C) 2001 Michael Teo <michaelteo@bigfoot.com>
  14. # nmb.py - NetBIOS library
  15. #
  16. # This software is provided 'as-is', without any express or implied warranty. 
  17. # In no event will the author be held liable for any damages arising from the 
  18. # use of this software.
  19. #
  20. # Permission is granted to anyone to use this software for any purpose, 
  21. # including commercial applications, and to alter it and redistribute it 
  22. # freely, subject to the following restrictions:
  23. #
  24. # 1. The origin of this software must not be misrepresented; you must not 
  25. #    claim that you wrote the original software. If you use this software 
  26. #    in a product, an acknowledgment in the product documentation would be
  27. #    appreciated but is not required.
  28. #
  29. # 2. Altered source versions must be plainly marked as such, and must not be 
  30. #    misrepresented as being the original software.
  31. #
  32. # 3. This notice cannot be removed or altered from any source distribution.
  33. #
  34. # Altered source done by Alberto Solino
  35.  
  36. import os, sys, socket, string, re, select, errno
  37. from random import randint
  38. from struct import *
  39.  
  40.  
  41. CVS_REVISION = '$Revision: 1.4 $'
  42.  
  43. # Taken from socket module reference
  44. INADDR_ANY = ''
  45. BROADCAST_ADDR = '<broadcast>'
  46.  
  47. # Default port for NetBIOS name service
  48. NETBIOS_NS_PORT = 137
  49. # Default port for NetBIOS session service
  50. NETBIOS_SESSION_PORT = 139
  51.  
  52. # Default port for SMB session service
  53. SMB_SESSION_PORT = 445
  54.  
  55. # Owner Node Type Constants
  56. NODE_B = 0x0000
  57. NODE_P = 0x2000
  58. NODE_M = 0x4000
  59. NODE_RESERVED = 0x6000
  60. NODE_GROUP = 0x8000
  61. NODE_UNIQUE = 0x0
  62.  
  63. # Name Type Constants
  64. TYPE_UNKNOWN = 0x01
  65. TYPE_WORKSTATION = 0x00
  66. TYPE_CLIENT = 0x03
  67. TYPE_SERVER = 0x20
  68. TYPE_DOMAIN_MASTER = 0x1B
  69. TYPE_MASTER_BROWSER = 0x1D
  70. TYPE_BROWSER = 0x1E
  71. TYPE_NETDDE  = 0x1F
  72.  
  73. # Opcodes values
  74. OPCODE_QUERY = 0
  75. OPCODE_REGISTRATION = 0x5
  76. OPCODE_RELEASE = 0x6
  77. OPCODE_WACK = 0x7
  78. OPCODE_REFRESH = 0x8
  79. OPCODE_REQUEST = 0
  80. OPCODE_RESPONSE = 0x10
  81.  
  82. # NM_FLAGS
  83. NM_FLAGS_BROADCAST = 0x1
  84. NM_FLAGS_UNICAST = 0
  85. NM_FLAGS_RA = 0x8
  86. NM_FLAGS_RD = 0x10
  87. NM_FLAGS_TC = 0x20
  88. NM_FLAGS_AA = 0x40
  89.  
  90. # QUESTION_TYPE
  91. QUESTION_TYPE_NB = 0x20     # NetBIOS general Name Service Resource Record
  92. QUESTION_TYPE_NBSTAT = 0x21 # NetBIOS NODE STATUS Resource Record
  93. # QUESTION_CLASS
  94. QUESTION_CLASS_IN = 0x1     # Internet class
  95.  
  96. # RR_TYPE Resource Record Type code
  97. RR_TYPE_A = 0x1               # IP address Resource Record
  98. RR_TYPE_NS = 0x2              # Name Server Resource Record
  99. RR_TYPE_NULL = 0xA          # NULL Resource Record
  100. RR_TYPE_NB = 0x20           # NetBIOS general Name Service Resource Record
  101. RR_TYPE_NBSTAT = 0x21       # NetBIOS NODE STATUS Resource Record
  102.  
  103. # Resource Record Class
  104. RR_CLASS_IN = 1             # Internet class
  105.  
  106. # RCODE values
  107. RCODE_FMT_ERR   = 0x1       # Format Error.  Request was invalidly formatted.
  108. RCODE_SRV_ERR   = 0x2       # Server failure.  Problem with NBNS, cannot process name.
  109. RCODE_IMP_ERR   = 0x4       # Unsupported request error.  Allowable only for challenging NBNS when gets an Update type
  110.                             # registration request.
  111. RCODE_RFS_ERR   = 0x5       # Refused error.  For policy reasons server will not register this name from this host.
  112. RCODE_ACT_ERR   = 0x6       # Active error.  Name is owned by another node.
  113. RCODE_CFT_ERR   = 0x7       # Name in conflict error.  A UNIQUE name is owned by more than one node.
  114.  
  115. # NAME_FLAGS
  116. NAME_FLAGS_PRM = 0x0200       # Permanent Name Flag.  If one (1) then entry is for the permanent node name.  Flag is zero
  117.                             # (0) for all other names.
  118. NAME_FLAGS_ACT = 0x0400       # Active Name Flag.  All entries have this flag set to one (1).
  119. NAME_FLAG_CNF  = 0x0800       # Conflict Flag.  If one (1) then name on this node is in conflict.
  120. NAME_FLAG_DRG  = 0x1000       # Deregister Flag.  If one (1) then this name is in the process of being deleted.
  121.  
  122. NAME_TYPES = { TYPE_UNKNOWN: 'Unknown', TYPE_WORKSTATION: 'Workstation', TYPE_CLIENT: 'Client',
  123.                TYPE_SERVER: 'Server', TYPE_MASTER_BROWSER: 'Master Browser', TYPE_BROWSER: 'Browser Server',
  124.                TYPE_DOMAIN_MASTER: 'Domain Master' , TYPE_NETDDE: 'NetDDE Server'}
  125. # NetBIOS Session Types
  126. NETBIOS_SESSION_MESSAGE = 0x0
  127. NETBIOS_SESSION_REQUEST = 0x81
  128. NETBIOS_SESSION_POSITIVE_RESPONSE = 0x82
  129. NETBIOS_SESSION_NEGATIVE_RESPONSE = 0x83
  130. NETBIOS_SESSION_RETARGET_RESPONSE = 0x84
  131. NETBIOS_SESSION_KEEP_ALIVE = 0x85
  132.  
  133.  
  134. def strerror(errclass, errcode):
  135.     if errclass == ERRCLASS_OS:
  136.         return 'OS Error', os.strerror(errcode)
  137.     elif errclass == ERRCLASS_QUERY:
  138.         return 'Query Error', QUERY_ERRORS.get(errcode, 'Unknown error')
  139.     elif errclass == ERRCLASS_SESSION:
  140.         return 'Session Error', SESSION_ERRORS.get(errcode, 'Unknown error')
  141.     else:
  142.         return 'Unknown Error Class', 'Unknown Error'
  143.     
  144.     
  145.  
  146. class NetBIOSError(Exception): pass
  147. class NetBIOSTimeout(Exception):
  148.     def __init__(self, message = 'The NETBIOS connection with the remote host timed out.'):
  149.         Exception.__init__(self, message)
  150.  
  151. class NBResourceRecord:
  152.     def __init__(self, data = 0):
  153.         self._data = data
  154.         try:
  155.             if self._data:
  156.                 self.rr_name = (re.split('\x00',data))[0]
  157.                 offset = len(self.rr_name)+1
  158.                 self.rr_type  = unpack('>H', self._data[offset:offset+2])[0]
  159.                 self.rr_class = unpack('>H', self._data[offset+2: offset+4])[0]
  160.                 self.ttl = unpack('>L',self._data[offset+4:offset+8])[0]
  161.                 self.rdlength = unpack('>H', self._data[offset+8:offset+10])[0]
  162.                 self.rdata = data[offset+10:self.rdlength]
  163.                 offset = self.rdlength - 2
  164.                 self.unit_id = data[offset:offset+6]
  165.             else:
  166.                 self.rr_name = ''
  167.                 self.rr_type = 0
  168.                 self.rr_class = 0
  169.                 self.ttl = 0
  170.                 self.rdlength = 0
  171.                 self.rdata = ''
  172.                 self.unit_id = ''
  173.         except Exception,e:
  174.                 raise NetBIOSError( 'Wrong packet format ' )
  175.  
  176.     def set_rr_name(self, name):
  177.         self.rr_name = name
  178.     def set_rr_type(self, name):
  179.         self.rr_type = name
  180.     def set_rr_class(self,cl):
  181.         self_rr_class = cl
  182.     def set_ttl(self,ttl):
  183.         self.ttl = ttl
  184.     def set_rdata(self,rdata):
  185.         self.rdata = rdata
  186.         self.rdlength = len(rdata)
  187.     def get_unit_id(self):
  188.         return self.unit_id
  189.     def get_rr_name(self):
  190.         return self.rr_name
  191.     def get_rr_class(self):
  192.         return self.rr_class
  193.     def get_ttl(self):
  194.         return self.ttl
  195.     def get_rdlength(self):
  196.         return self.rdlength
  197.     def get_rdata(self):
  198.         return self.rdata
  199.     def rawData(self):
  200.         return self.rr_name + pack('!HHLH',self.rr_type, self.rr_class, self.ttl, self.rdlength) + self.rdata
  201.  
  202. class NBNodeStatusResponse(NBResourceRecord):
  203.     def __init__(self, data = 0):
  204.         NBResourceRecord.__init__(self,data)
  205.         self.num_names = 0
  206.         self.node_names = [ ]
  207.         self.statstics = ''
  208.         self.mac = '00-00-00-00-00-00'
  209.         try:
  210.             if data:
  211.                 self._data = self.get_rdata()
  212.                 self.num_names = unpack('>B',self._data[:1])[0]
  213.                 offset = 1
  214.                 for i in range(0, self.num_names):
  215.                     name = self._data[offset:offset + 15]
  216.                     type,flags = unpack('>BH', self._data[offset + 15: offset + 18])
  217.                     offset += 18
  218.                     self.node_names.append(NBNodeEntry(name, type ,flags))
  219.                 self.set_mac_in_hexa(self.get_unit_id())
  220.         except Exception,e:
  221.             raise NetBIOSError( 'Wrong packet format ' )
  222.  
  223.     def set_mac_in_hexa(self, data):
  224.         data_aux = ''
  225.         for d in data:
  226.             if data_aux == '':
  227.                 data_aux = '%02x' % ord(d)
  228.             else:
  229.                 data_aux += '-%02x' % ord(d)
  230.         self.mac = string.upper(data_aux)
  231.  
  232.     def get_num_names(self):
  233.         return self.num_names
  234.     def get_mac(self):
  235.         return self.mac
  236.     def set_num_names(self, num):
  237.         self.num_names = num
  238.     def get_node_names(self):
  239.         return self.node_names
  240.     def add_node_name(self,node_names):
  241.         self.node_names.append(node_names)
  242.         self.num_names += 1
  243.     def rawData(self):
  244.         res = pack('!B', self.num_names )
  245.         for i in range(0, self.num_names):
  246.             res += self.node_names[i].rawData()
  247.  
  248. class NBPositiveNameQueryResponse(NBResourceRecord):
  249.     def __init__(self,data = 0):
  250.         NBResourceRecord.__init__(self,data)
  251.         self.add_entries = [ ]
  252.         if data:
  253.                 self._data = self.get_rdata()
  254.                 
  255. class NetBIOSPacket:
  256.     """ This is a packet as defined in RFC 1002 """
  257.     def __init__(self, data = 0):
  258.         self.name_trn_id = 0x0 # Transaction ID for Name Service Transaction.
  259.                              #   Requestor places a unique value for each active
  260.                              #   transaction.  Responder puts NAME_TRN_ID value
  261.                              #   from request packet in response packet.
  262.         self.opcode = 0      # Packet type code
  263.         self.nm_flags = 0    # Flags for operation
  264.         self.rcode = 0       # Result codes of request.
  265.         self.qdcount = 0     # Unsigned 16 bit integer specifying the number of entries in the question section of a Name
  266.         self.ancount = 0     # Unsigned 16 bit integer specifying the number of
  267.                              # resource records in the answer section of a Name
  268.                              # Service packet.
  269.         self.nscount = 0     # Unsigned 16 bit integer specifying the number of
  270.                              # resource records in the authority section of a
  271.                              # Name Service packet.
  272.         self.arcount = 0     # Unsigned 16 bit integer specifying the number of
  273.                              # resource records in the additional records
  274.                              # section of a Name Service packeT.
  275.         self.questions = ''
  276.         self.answers = ''
  277.         if data == 0:
  278.             self._data = ''
  279.         else:
  280.             try:
  281.                 self._data = data
  282.                 self.opcode = ord(data[2]) >> 3 
  283.                 self.nm_flags = ((ord(data[2]) & 0x3) << 4) | ((ord(data[3]) & 0xf0) >> 4)
  284.                 self.name_trn_id = unpack('>H', self._data[:2])[0]
  285.                 self.rcode = ord(data[3]) & 0x0f
  286.                 self.qdcount = unpack('>H', self._data[4:6])[0]
  287.                 self.ancount = unpack('>H', self._data[6:8])[0]
  288.                 self.nscount = unpack('>H', self._data[8:10])[0]
  289.                 self.arcount = unpack('>H', self._data[10:12])[0]
  290.                 self.answers = self._data[12:]
  291.             except Exception,e:
  292.                 raise NetBIOSError( 'Wrong packet format ' )
  293.             
  294.     def set_opcode(self, opcode):
  295.         self.opcode = opcode
  296.     def set_trn_id(self, trn):
  297.         self.name_trn_id = trn
  298.     def set_nm_flags(self, nm_flags):
  299.         self.nm_flags = nm_flags
  300.     def set_rcode(self, rcode):
  301.         self.rcode = rcode
  302.     def addQuestion(self, question, qtype, qclass):
  303.         self.qdcount = self.qdcount + 1
  304.         self.questions += question + pack('!HH',qtype,qclass)
  305.     def get_trn_id(self):
  306.         return self.name_trn_id
  307.     def get_rcode(self):
  308.         return self.rcode
  309.     def get_nm_flags(self):
  310.         return self.name_trn_id
  311.     def get_opcode(self):
  312.         return self.opcode
  313.     def get_qdcount(self):
  314.         return self.qdcount
  315.     def get_ancount(self):
  316.         return self.ancount
  317.     def get_nscount(self):
  318.         return self.nscount
  319.     def get_arcount(self):
  320.         return self.arcount
  321.     def rawData(self):
  322.         secondWord = self.opcode << 11
  323.         secondWord = secondWord | (self.nm_flags << 4)
  324.         secondWord = secondWord | self.rcode
  325.         data = pack('!HHHHHH', self.name_trn_id, secondWord , self.qdcount, self.ancount, self.nscount, self.arcount) + self.questions + self.answers
  326.         return data
  327.     def get_answers(self):
  328.         return self.answers
  329.  
  330. class NBHostEntry:
  331.  
  332.     def __init__(self, nbname, nametype, ip):
  333.         self.__nbname = nbname
  334.         self.__nametype = nametype
  335.         self.__ip = ip
  336.  
  337.     def get_nbname(self):
  338.         return self.__nbname
  339.  
  340.     def get_nametype(self):
  341.         return self.__nametype
  342.  
  343.     def get_ip(self):
  344.         return self.__ip
  345.  
  346.     def __repr__(self):
  347.         return '<NBHostEntry instance: NBname="' + self.__nbname + '", IP="' + self.__ip + '">'
  348.  
  349.  
  350.  
  351. class NBNodeEntry:
  352.     
  353.     def __init__(self, nbname, nametype, flags): 
  354.         self.__nbname = string.ljust(nbname,17)
  355.         self.__nametype = nametype
  356.         self.__flags = flags
  357.         self.__isgroup = flags & 0x8000
  358.         self.__nodetype = flags & 0x6000
  359.         self.__deleting = flags & 0x1000
  360.         self.__isconflict = flags & 0x0800
  361.         self.__isactive = flags & 0x0400
  362.         self.__ispermanent = flags & 0x0200
  363.  
  364.     def get_nbname(self):
  365.         return self.__nbname
  366.  
  367.     def get_nametype(self):
  368.         return self.__nametype
  369.  
  370.     def is_group(self):
  371.         return self.__isgroup
  372.  
  373.     def get_nodetype(self):
  374.         return self.__nodetype
  375.  
  376.     def is_deleting(self):
  377.         return self.__deleting
  378.  
  379.     def is_conflict(self):
  380.         return self.__isconflict
  381.  
  382.     def is_active(self):
  383.         return self.__isactive
  384.  
  385.     def is_permanent(self):
  386.         return self.__ispermanent
  387.  
  388.     def set_nbname(self, name):
  389.         self.__nbname = string.ljust(name,17)
  390.  
  391.     def set_nametype(self, type):
  392.         self.__nametype = type
  393.  
  394.     def set_flags(self,flags):
  395.         self.__flags = flags
  396.         
  397.     def __repr__(self):
  398.         s = '<NBNodeEntry instance: NBname="' + self.__nbname + '" NameType="' + NAME_TYPES[self.__nametype] + '"'
  399.         if self.__isactive:
  400.             s = s + ' ACTIVE'
  401.         if self.__isgroup:
  402.             s = s + ' GROUP'
  403.         if self.__isconflict:
  404.             s = s + ' CONFLICT'
  405.         if self.__deleting:
  406.             s = s + ' DELETING'
  407.         return s
  408.     def rawData(self):
  409.         return self.__nbname + pack('!BH',self.__nametype, self.__flags)
  410.  
  411.  
  412. class NetBIOS:
  413.  
  414.     # Creates a NetBIOS instance without specifying any default NetBIOS domain nameserver.
  415.     # All queries will be sent through the servport.
  416.     def __init__(self, servport = NETBIOS_NS_PORT):
  417.         s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  418. #        s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
  419.         has_bind = 1
  420.         for i in range(0, 10):
  421.         # We try to bind to a port for 10 tries
  422.             try:
  423.                 s.bind(( INADDR_ANY, randint(10000, 60000) ))
  424.                 s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
  425.                 has_bind = 1
  426.             except socket.error, ex:
  427.                 pass
  428.         if not has_bind:
  429.             raise NetBIOSError, ( 'Cannot bind to a good UDP port', ERRCLASS_OS, errno.EAGAIN )
  430.  
  431.         self.__sock = s
  432.         self.__servport = NETBIOS_NS_PORT
  433.         self.__nameserver = None
  434.         self.__broadcastaddr = BROADCAST_ADDR
  435.         self.mac = '00-00-00-00-00-00'
  436.  
  437.     # Set the default NetBIOS domain nameserver.
  438.     def set_nameserver(self, nameserver):
  439.         self.__nameserver = nameserver
  440.  
  441.     # Return the default NetBIOS domain nameserver, or None if none is specified.
  442.     def get_nameserver(self):
  443.         return self.__nameserver
  444.  
  445.     # Set the broadcast address to be used for query.
  446.     def set_broadcastaddr(self, broadcastaddr):
  447.         self.__broadcastaddr = broadcastaddr
  448.  
  449.     # Return the broadcast address to be used, or BROADCAST_ADDR if default broadcast address is used.   
  450.     def get_broadcastaddr(self):
  451.         return self.__broadcastaddr
  452.  
  453.     # Returns a list of NBHostEntry instances containing the host information for nbname.
  454.     # If a NetBIOS domain nameserver has been specified, it will be used for the query.
  455.     # Otherwise, the query is broadcasted on the broadcast address.
  456.     def gethostbyname(self, nbname, type = TYPE_WORKSTATION, scope = None, timeout = 1):
  457.         return self.__queryname(nbname, self.__nameserver, type, scope, timeout)
  458.  
  459.     # Returns a list of NBNodeEntry instances containing node status information for nbname.
  460.     # If destaddr contains an IP address, then this will become an unicast query on the destaddr.
  461.     # Raises NetBIOSTimeout if timeout (in secs) is reached.
  462.     # Raises NetBIOSError for other errors
  463.     def getnodestatus(self, nbname, destaddr = None, type = TYPE_WORKSTATION, scope = None, timeout = 1):
  464.         if destaddr:
  465.             return self.__querynodestatus(nbname, destaddr, type, scope, timeout)
  466.         else:
  467.             return self.__querynodestatus(nbname, self.__nameserver, type, scope, timeout)
  468.  
  469.     def getmacaddress(self):
  470.         return self.mac
  471.  
  472.     def __queryname(self, nbname, destaddr, type, scope, timeout):
  473.         netbios_name = string.upper(nbname)
  474.         trn_id = randint(1, 32000)
  475.         p = NetBIOSPacket()
  476.         p.set_trn_id(trn_id)
  477.         netbios_name = string.upper(nbname)
  478.         qn_label = encode_name(netbios_name, type, scope)
  479.         p.addQuestion(qn_label, QUESTION_TYPE_NB, QUESTION_CLASS_IN)
  480.         qn_label = encode_name(netbios_name, type, scope)
  481.         if not destaddr:
  482.             p.set_nm_flags(NM_FLAGS_BROADCAST)
  483.             destaddr = self.__broadcastaddr            
  484.         wildcard_query = netbios_name == '*'
  485.         req = p.rawData()
  486.         self.__sock.sendto(req, 0, ( destaddr, self.__servport ))
  487.         addrs = [ ]
  488.         tries = 3
  489.         while 1:
  490.             try:
  491.                 ready, _, _ = select.select([ self.__sock.fileno() ], [ ] , [ ], timeout)
  492.                 if not ready:
  493.                     if tries and not wildcard_query:
  494.                         # Retry again until tries == 0
  495.                         self.__sock.sendto(req, 0, ( destaddr, self.__servport ))
  496.                         tries = tries - 1
  497.                     elif wildcard_query:
  498.                         return addrs
  499.                     else:
  500.                         raise NetBIOSTimeout
  501.                 else:
  502.                     data, _ = self.__sock.recvfrom(65536, 0)
  503.                     res = NetBIOSPacket(data)
  504.                     if res.get_trn_id() == p.get_trn_id():
  505.                         if res.get_rcode():
  506.                             if res.get_rcode() == 0x03:
  507.                                 return None
  508.                             else:
  509.                                 raise NetBIOSError, ( 'Negative name query response', ERRCLASS_QUERY, res.get_rcode() )
  510.                         answ = NBPositiveNameQueryResponse(res.get_answers())
  511.                         if not wildcard_query:
  512.                             return addrs
  513.             except select.error, ex:
  514.                 if ex[0] != errno.EINTR and ex[0] != errno.EAGAIN:
  515.                     raise NetBIOSError, ( 'Error occurs while waiting for response', ERRCLASS_OS, ex[0] )
  516.             except socket.error, ex:
  517.                 pass
  518.  
  519.     def __querynodestatus(self, nbname, destaddr, type, scope, timeout):
  520.         trn_id = randint(1, 32000)
  521.         p = NetBIOSPacket()
  522.         p.set_trn_id(trn_id)
  523.         netbios_name = string.upper(nbname)
  524.         qn_label = encode_name(netbios_name, type, scope)
  525.         p.addQuestion(qn_label, QUESTION_TYPE_NBSTAT, QUESTION_CLASS_IN)
  526.  
  527.         if not destaddr:
  528.             p.set_nm_flags(NM_FLAGS_BROADCAST)
  529.             destaddr = self.__broadcastaddr            
  530.         req = p.rawData()
  531.         tries = 3
  532.         while 1:
  533.             try:
  534.                 self.__sock.sendto(req, 0, ( destaddr, self.__servport ))
  535.                 ready, _, _ = select.select([ self.__sock.fileno() ], [ ] , [ ], timeout)
  536.                 if not ready:
  537.                     if tries:
  538.                         # Retry again until tries == 0
  539.                         tries = tries - 1
  540.                     else:
  541.                         raise NetBIOSTimeout
  542.                 else:
  543.                     try:
  544.                         data, _ = self.__sock.recvfrom(65536, 0)
  545.                     except:
  546. #                        t_log(1,"No status response")
  547.                         return
  548.                     res = NetBIOSPacket(data)
  549.                     if res.get_trn_id() == p.get_trn_id():
  550.                         if res.get_rcode():
  551.                             if res.get_rcode() == 0x03:
  552.                                 return None
  553.                             else:
  554.                                 raise NetBIOSError, ( 'Negative name query response', ERRCLASS_QUERY, res.get_rcode() )
  555.                         answ = NBNodeStatusResponse(res.get_answers())
  556.                         self.mac = answ.get_mac()
  557.                         return answ.get_node_names()
  558.             except select.error, ex:
  559.                 if ex[0] != errno.EINTR and ex[0] != errno.EAGAIN:
  560.                     raise NetBIOSError, ( 'Error occurs while waiting for response', ERRCLASS_OS, ex[0] )
  561.             except socket.error, ex:
  562.                 pass
  563.         
  564.  
  565.  
  566. # Perform first and second level encoding of name as specified in RFC 1001 (Section 4)
  567. def encode_name(name, type, scope):
  568.     if name == '*':
  569.         name = name + '\0' * 15
  570.     elif len(name) > 15:
  571.         name = name[:15] + chr(type)
  572.     else:
  573.         name = string.ljust(name, 15) + chr(type)
  574.         
  575.     encoded_name = chr(len(name) * 2) + re.sub('.', _do_first_level_encoding, name)
  576.     if scope:
  577.         encoded_scope = ''
  578.         for s in string.split(scope, '.'):
  579.             encoded_scope = encoded_scope + chr(len(s)) + s
  580.         return encoded_name + encoded_scope + '\0'
  581.     else:
  582.         return encoded_name + '\0'
  583.  
  584. # Internal method for use in encode_name()
  585. def _do_first_level_encoding(m):
  586.     s = ord(m.group(0))
  587.     return string.uppercase[s >> 4] + string.uppercase[s & 0x0f]
  588.  
  589. def decode_name(name):
  590.     name_length = ord(name[0])
  591.     assert name_length == 32
  592.  
  593.     decoded_name = re.sub('..', _do_first_level_decoding, name[1:33])
  594.     if name[33] == '\0':
  595.         return 34, decoded_name, ''
  596.     else:
  597.         decoded_domain = ''
  598.         offset = 34
  599.         while 1:
  600.             domain_length = ord(name[offset])
  601.             if domain_length == 0:
  602.                 break
  603.             decoded_domain = '.' + name[offset:offset + domain_length]
  604.             offset = offset + domain_length
  605.         return offset + 1, decoded_name, decoded_domain
  606.  
  607. def _do_first_level_decoding(m):
  608.     s = m.group(0)
  609.     return chr(((ord(s[0]) - ord('A')) << 4) | (ord(s[1]) - ord('A')))
  610.  
  611.  
  612.  
  613. class NetBIOSSessionPacket:
  614.     def __init__(self, data = 0):
  615.         self.type = 0x0 
  616.         self.flags = 0x0
  617.         self.length = 0x0
  618.         if data == 0:
  619.             self._trailer = ''
  620.         else:
  621.             try:
  622.                 self.type = ord(data[0])
  623.                 self.flags = ord(data[1])
  624.                 self.length = unpack('!H', data[2:4])[0]
  625.                 self._trailer = data[4:]
  626.             except:
  627.                 raise NetBIOSError( 'Wrong packet format ' )
  628.  
  629.     def set_type(self, type):
  630.         self.type = type
  631.     def get_type(self):
  632.         return self.type
  633.     def rawData(self):
  634.         data = pack('!BBH',self.type,self.flags,self.length) + self._trailer
  635.         return data
  636.     def set_trailer(self,data):
  637.         self._trailer = data
  638.         self.length = len(data)
  639.     def get_length(self):
  640.         return self.length
  641.     def get_trailer(self):
  642.         return self._trailer
  643.         
  644. class NetBIOSSession:
  645.  
  646.     def __init__(self, myname, remote_name, remote_host, remote_type = TYPE_SERVER, sess_port = NETBIOS_SESSION_PORT, timeout = None, local_type = TYPE_WORKSTATION):
  647.         if len(myname) > 15:
  648.             self.__myname = string.upper(myname[:15])
  649.         else:
  650.             self.__myname = string.upper(myname)
  651.  
  652.         assert remote_name
  653.         if len(remote_name) > 15:
  654.             self.__remote_name = string.upper(remote_name[:15])
  655.         else:
  656.             self.__remote_name = string.upper(remote_name)
  657.  
  658.         self.__remote_host = remote_host
  659.         self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  660.         try:
  661.             self.__sock.connect(( remote_host, sess_port ))
  662.         except socket.error, ex:
  663.             raise ex
  664.  
  665.         if sess_port == NETBIOS_SESSION_PORT:
  666.             self.__request_session(remote_type, local_type, timeout)
  667.      
  668.     def get_myname(self):
  669.         return self.__myname
  670.  
  671.     def get_remote_host(self):
  672.         return self.__remote_host
  673.  
  674.     def get_remote_name(self):
  675.         return self.__remote_name
  676.  
  677.     def close(self):
  678.         self.__sock.close()
  679.  
  680.     def send_packet(self, data):
  681.         p = NetBIOSSessionPacket()
  682.         p.set_type(NETBIOS_SESSION_MESSAGE)
  683.         p.set_trailer(data)
  684.         self.__sock.send(p.rawData())
  685.  
  686.     def recv_packet(self, timeout = None):
  687.         data = self.__read(timeout)
  688.         return NetBIOSSessionPacket(data)
  689.  
  690.     def __request_session(self, remote_type, local_type, timeout = None):
  691.         p = NetBIOSSessionPacket()
  692.         remote_name = encode_name(self.__remote_name, remote_type, '')
  693.         myname = encode_name(self.__myname, local_type, '')
  694.         p.set_type(NETBIOS_SESSION_REQUEST)
  695.         p.set_trailer(remote_name + myname)
  696.         self.__sock.send(p.rawData())
  697.         while 1:
  698.             p = self.recv_packet(timeout)
  699.             if p.get_type() == NETBIOS_SESSION_NEGATIVE_RESPONSE:
  700.                 raise NetBIOSError, ( 'Cannot request session', ERRCLASS_SESSION, ord(p.get_trailer()[0]) )
  701.             elif p.get_type() == NETBIOS_SESSION_POSITIVE_RESPONSE:
  702.                 break
  703.             else:
  704.                 # Ignore all other messages, most probably keepalive messages
  705.                 pass
  706.  
  707.     def __read(self, timeout = None):
  708.         read_len = 4
  709.         data = ''
  710.         while read_len > 0:
  711.             try:
  712.                 ready, _, _ = select.select([self.__sock.fileno() ], [ ], [ ], timeout)
  713.                 if not ready:
  714.                     raise NetBIOSTimeout
  715.  
  716.                 received = self.__sock.recv(read_len)
  717.                 if len(received)==0:
  718.                     raise NetBIOSError, ( 'Error while reading from remote', ERRCLASS_OS, None)
  719.                 
  720.                 data = data + received
  721.                 read_len = 4 - len(data)
  722.             except select.error, ex:
  723.                 if ex[0] != errno.EINTR and ex[0] != errno.EAGAIN:
  724.                     raise NetBIOSError, ( 'Error occurs while reading from remote', ERRCLASS_OS, ex[0] )
  725.                 
  726.         type, flags, length = unpack('>ccH', data)
  727.         if ord(flags) & 0x01:
  728.             length = length | 0x10000
  729.             
  730.         read_len = length
  731.         data2=''
  732.         while read_len > 0:
  733.             try:
  734.                 ready, _, _ = select.select([ self.__sock.fileno() ], [ ], [ ], timeout)
  735.                 if not ready:
  736.                     raise NetBIOSTimeout
  737.  
  738.                 received = self.__sock.recv(read_len)
  739.                 if len(received)==0:
  740.                     raise NetBIOSError, ( 'Error while reading from remote', ERRCLASS_OS, None)
  741.                 
  742.                 data2 = data2 + received 
  743.                 read_len = length - len(data2)
  744.             except select.error, ex:
  745.                 if ex[0] != errno.EINTR and ex[0] != errno.EAGAIN:
  746.                     raise NetBIOSError, ( 'Error while reading from remote', ERRCLASS_OS, ex[0] )
  747.                 
  748.         return data + data2     
  749.  
  750.     def get_socket(self):
  751.         return self.__sock
  752.  
  753.  
  754. ERRCLASS_QUERY = 0x00
  755. ERRCLASS_SESSION = 0xf0
  756. ERRCLASS_OS = 0xff
  757.  
  758. QUERY_ERRORS = { 0x01: 'Request format error. Please file a bug report.',
  759.                  0x02: 'Internal server error',
  760.                  0x03: 'Name does not exist',
  761.                  0x04: 'Unsupported request',
  762.                  0x05: 'Request refused'
  763.                  }
  764.  
  765. SESSION_ERRORS = { 0x80: 'Not listening on called name',
  766.                    0x81: 'Not listening for calling name',
  767.                    0x82: 'Called name not present',
  768.                    0x83: 'Sufficient resources',
  769.                    0x8f: 'Unspecified error'
  770.                    }
  771.  
  772. def main():
  773.     print
  774.  
  775. if __name__ == '__main__':
  776.     main()
  777.